package com.dmagic.cms.service.impl;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import javax.persistence.RollbackException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.dmagic.cms.common.dao.CommonDao;
import com.dmagic.cms.common.entity.ModifyInfoEntity;
import com.dmagic.cms.common.exception.ServiceException;
import com.dmagic.cms.common.exception.ValidateException;
import com.dmagic.cms.common.service.CommonService;
import com.dmagic.cms.common.util.FileUtil;
import com.dmagic.cms.common.util.NumberUtil;
import com.dmagic.cms.common.util.PropertiesUtils;
import com.dmagic.cms.common.util.StringUtil;
import com.dmagic.cms.common.util.reflection.ConvertUtil;
import com.dmagic.cms.dao.LanguageDao;
import com.dmagic.cms.dao.UploadFileInfoDao;
import com.dmagic.cms.dao.UploadFileSetInfoDao;
import com.dmagic.cms.entity.Language;
import com.dmagic.cms.entity.UploadFileInfo;
import com.dmagic.cms.entity.UploadFileSetInfo;
import com.dmagic.cms.service.BaseService;

@Service
@Transactional(readOnly = true, rollbackFor = { ValidateException.class, RollbackException.class })
public class BaseServiceImpl extends CommonService implements BaseService {

	private static String fileUploadSavePath;

	@Autowired
	private UploadFileInfoDao uploadFileInfoDao;

	@Autowired
	private UploadFileSetInfoDao uploadFileSetInfoDao;

	@Autowired
	private LanguageDao languageDao;

	static {
		Properties propertie = PropertiesUtils.loadProperties("classpath:application.properties");
		fileUploadSavePath = propertie.getProperty("fileUpload.savePath");
	}

	@Override
	public List<Language> getAllLanguages() {
		return languageDao.find("from Language where " + ModifyInfoEntity.ISOBSOLETE_DATE_IS_NULL);
	}

	@Override
	protected CommonDao getCommonDao() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	@Transactional(readOnly = false)
	public UploadFileInfo upload(CommonsMultipartFile uploadFile, Long uploadFileSetInfoId)
			throws ServiceException {

		if (uploadFile == null || uploadFile.isEmpty()) {
			throw new ServiceException("uploadFile can not be not!");
		}

		// ----upload file-----begin---
		logger.debug("###############ContentType:" + uploadFile.getContentType());
		logger.debug("###############OriginalFilename:" + uploadFile.getOriginalFilename());
		logger.debug("###############Size:" + uploadFile.getSize());
		logger.debug("###############Name:" + uploadFile.getName());
		logger.debug("###############StorageDescription:" + uploadFile.getStorageDescription());

		String oldFileName = uploadFile.getOriginalFilename();
		String fileExtensions = null;
		String fileType = null;
		if (StringUtil.isNotBlank(oldFileName)) {
			fileExtensions = oldFileName.substring(oldFileName.lastIndexOf('.'), oldFileName.length());
			fileType = oldFileName.substring(oldFileName.lastIndexOf('.') + 1, oldFileName.length());
		}
		String newFileName = System.currentTimeMillis() + fileExtensions;
		// ----check the toUploadPath----begin---
		FileUtil fileUtil = new FileUtil(fileUploadSavePath, newFileName);
		DataOutputStream out = null;
		InputStream is = null;
		try {
			fileUtil.createFile();
			out = new DataOutputStream(new FileOutputStream(fileUtil.getFile()));
			is = uploadFile.getInputStream();
			byte[] buffer = new byte[1024];
			while (is.read(buffer) > 0) {
				out.write(buffer);
			}
		} catch (Exception e1) {
			throw new ServiceException("The savePath in the application.properties has not configured", e1);
		} finally {
			fileUtil.close();
			try {
				if (is != null) {
					is.close();

				}
				if (out != null) {

					out.close();
				}
			} catch (IOException e) {
				logger.error("Stream Close Error:" + e.getMessage());
			}
		}
		// ----check the toUploadPath----end---

		String fileAbsPath = fileUploadSavePath + "/" + newFileName;

		logger.info("###################The file :[" + oldFileName + "],was uploaded to:[" + fileAbsPath
				+ "] successful!");

		// ----upload file-----end---
		// save fileUploadEntity--begin--------------
		UploadFileSetInfo uploadFileSetInfo = null;
		if (StringUtil.isNotBlank(uploadFileSetInfoId)) {
			uploadFileSetInfo = uploadFileSetInfoDao.getEntityById(uploadFileSetInfoId);
		}
		if (null == uploadFileSetInfo) {
			uploadFileSetInfo = new UploadFileSetInfo();
			this.uploadFileSetInfoDao.saveEntity(uploadFileSetInfo);
		} else {
			uploadFileSetInfo.setUploadFileSetInfoId(uploadFileSetInfoId);
		}

		UploadFileInfo uploadFileInfo = new UploadFileInfo();
		uploadFileInfo.setUploadFileSetInfoId(uploadFileSetInfo.getUploadFileSetInfoId());
		uploadFileInfo.setClientHostName(null);
		uploadFileInfo.setFileEncoding(uploadFile.getContentType());
		uploadFileInfo.setFileSize(uploadFile.getSize());
		uploadFileInfo.setFileName(oldFileName);
		uploadFileInfo.setFileType(fileType);
		uploadFileInfo.setLocation(fileAbsPath);
		this.uploadFileInfoDao.saveEntity(uploadFileInfo);
		// save fileUploadEntity--end--------------
		return uploadFileInfo;
	}

	@Override
	public List<UploadFileInfo> getUploadFileInfoListByUploadFileSetInfoId(Long uploadFileSetInfoId) {
		return uploadFileInfoDao.getUploadFileInfoListByUploadFileSetInfoId(uploadFileSetInfoId);
	}

	@Override
	public List<UploadFileInfo> getUploadFileInfoListIncludeDeleteInfoByUploadFileInfoIds(
			Long[] uploadFileInfoIds) {
		return uploadFileInfoDao.getUploadFileInfoListIncludeDeleteInfoByUploadFileInfoIds(uploadFileInfoIds);
	}

	@Override
	@Transactional(readOnly = false)
	public void deleteUploadFileInfoByUploadFileInfoId(Long uploadFileInfoId) throws RollbackException {
		this.uploadFileInfoDao.deleteEntityById(uploadFileInfoId);
	}

	@Override
	@Transactional(readOnly = false)
	public void deleteUploadFileInfoByUploadFileSetInfoId(Long uploadFileSetInfoId) throws RollbackException {
		this.uploadFileSetInfoDao.deleteById(uploadFileSetInfoId);
	}

	@Override
	public boolean checkUploadFileSetInfoId(Long uploadFileSetInfoId) {
		boolean isValid = true;
		int count = this.uploadFileInfoDao.getUploadFileInfoCountByUploadFileSetInfoId(uploadFileSetInfoId);
		if (count == 0) {
			this.uploadFileSetInfoDao.deleteById(uploadFileSetInfoId);
			isValid = false;
		}
		return isValid;
	}

	@Override
	public boolean checkUploadFileInfoId(Long uploadFileInfoId) {
		UploadFileInfo uploadFileInfo = uploadFileInfoDao.getEntityById(uploadFileInfoId);
		if (uploadFileInfo != null && uploadFileInfo.getIsObsoleteDate() == null) {
			return true;
		} else
			return false;
	}

	@Override
	public boolean checkExistingUploadFile(Long uploadFileSetInfoId, String fileName) {
		if (uploadFileSetInfoId == null || uploadFileSetInfoId == 0) {
			return false;
		}
		List<UploadFileInfo> uploadFileInfoList = getUploadFileInfoListByUploadFileSetInfoId(uploadFileSetInfoId);
		List<String> nameList = ConvertUtil.convertElementPropertyToList(uploadFileInfoList, "fileName");
		if (nameList.contains(fileName))
			return true;
		return false;
	}

	@Override
	public UploadFileInfo getUploadFileInfo(Long uploadFileInfoId) {
		return uploadFileInfoDao.getEntityById(uploadFileInfoId);
	}

	@Override
	@Transactional(readOnly = false)
	public void setMainFileByFileInfoId(Long uploadFileInfoId) {
		UploadFileInfo fileInfo = getUploadFileInfo(uploadFileInfoId);
		List<UploadFileInfo> fileInfos = getUploadFileInfoListByUploadFileSetInfoId(fileInfo.getUploadFileSetInfoId());
		for (UploadFileInfo uploadFileInfo : fileInfos) {
			if(NumberUtil.equals(uploadFileInfoId, uploadFileInfo.getUploadFileInfoId())){				
				uploadFileInfo.setIsMainFile(true);
			}else{
				uploadFileInfo.setIsMainFile(false);
			}
			uploadFileInfoDao.save(uploadFileInfo);
		}
	}
}
